package club.dingzm.myapplication.HttpBreakPoint;

import android.content.Context;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.HttpParams;
import com.lzy.okgo.model.Response;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.UUID;

import club.dingzm.myapplication.SPUtil;

public class HttpBreakpointUtil {

    private String TAG = "HttpBreakpointUtil";
    private String URL = "http://192.168.31.253:8111/ddxc/demo/uploadFileBytes";
    private Context context;


    private Boolean stopFlag = false;
    private String cacheId = "";
    private BreakpointInfo info = new BreakpointInfo();

    /**
     * 初始化 断点续传的功能 ，传入 文件路径，默认进行文件分片发送文件，从第一个分片开始
     * @param context
     * @param path 需上传文件的路径
     * @param cacheId 缓存Id 并且传入 后台当做文件夹
     */
    public void initSendFile(Context context, final String path,String cacheId){
        this.context= context;
        this.cacheId = cacheId;
        this.stopFlag = false;
        info = new BreakpointInfo(path);
        info.setTempFile(context.getExternalCacheDir()+"/"+ cacheId );
        HashMap hashMap = initParms();
        sendFile( (HttpParams)hashMap.get("HttpParams"), (File) hashMap.get("file") );
    }

    /**
     * 初始化 断点续传的功能 ，使用 缓存的缓存数据进行初始化
     * @param context
     * @param info 缓存已上传的 文件相关信息
     * @param cacheId 缓存Id 并且传入 后台当做文件夹
     */
    public void initSendFile(Context context, BreakpointInfo info,String cacheId){
        this.context = context;
        this.cacheId = cacheId;
        this.info = info;
        stopFlag = false;
        HashMap hashMap = initParms();
        sendFile( (HttpParams)hashMap.get("HttpParams"), (File) hashMap.get("file") );
    }
    //初始化上传参数
    private HashMap initParms(  ){
        HashMap res = new HashMap();
        
        HttpParams params = new HttpParams();
        params.put("fileName",info.getFile().getName());
        params.put("start",info.getCurrentBlock());
        params.put("end",info.getBLOCK_SIZE());
        params.put("md5",info.getMd5Hsh());
        params.put("cacheId",cacheId);
        File file = SliceFile();
        params.put("file",file);
        res.put("HttpParams",params);
        res.put("file",file);
        return  res;

    }

    //分片文件
    private File SliceFile() {
        File tempfile = new File(info.getTempFile()+"/"+info.getCurrentBlock()+"-"+info.getFile().getName());
        FileInputStream in = null;
        OutputStream out = null;
        try {
            if ( !tempfile.exists() ){
                tempfile.createNewFile();
            }
            in = new FileInputStream(info.getFile());
            out = new FileOutputStream(tempfile);

            //跳到对应的 位置分片继续写入 临时文件
            long seekStart  = 0;
            if ( info.getCurrentBlock() != 0){
                seekStart = info.getCurrentBlock() *  BreakpointInfo.CHUNK_SIZE;
            }
            if (seekStart == -1) {
                seekStart = 0;
            }
            in.skip(seekStart);


            long seekEnd  = ( info.getCurrentBlock() +1 ) *  BreakpointInfo.CHUNK_SIZE;

            int len;
            byte[] buf = new byte[1024];
            while ((len = in.read(buf)) >= 0 && seekStart < seekEnd) {
                out.write(buf, 0, len);
                seekStart += len;
                if (seekStart + 1024 > seekEnd) {
                    buf = new byte[Integer.valueOf((seekEnd - seekStart) + "")];
                }
            }
            return tempfile;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    //发送 http请求
    private void sendFile(HttpParams params , final File file){
        OkGo.<String>post(URL)
                .tag(this)
                .params(params)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(com.lzy.okgo.model.Response<String> response) {
                        try {
                            JSONObject obj = JSONObject.parseObject (response.body());
                            //返回 正常
                            if (obj.getInteger("code") == 200){
                                SPUtil.put(context, cacheId, JSONObject.toJSONString(info));
                                System.out.println("第"+info.getCurrentBlock()+"块内容返回："+obj);
                                //未设置 停止时
                                if (!stopFlag){
                                    //当不是最后一块文件的时候
                                    if (info.getCurrentBlock() != info.getBLOCK_SIZE() ){
                                        info.setCurrentBlock( info.getCurrentBlock() +1 ) ;
                                        HashMap hashMap = initParms();
                                        sendFile( (HttpParams)hashMap.get("HttpParams"), (File) hashMap.get("file") );
                                    }else{
                                        SPUtil.remove(context,cacheId);
                                        info.setSuccess(true);
                                        setStop(true);
                                    }
                                }else{
                                    System.out.println("停止发送文件！！！");
                                }
                            }else{
                                SPUtil.remove(context,cacheId);
                                setStop(true);
                                Log.e(TAG, "服务器出现错误: "+obj.getString("message") );
//                                Toast.makeText(context, "服务器出现错误！", Toast.LENGTH_SHORT).show();
                            }
                        } catch (Exception ex) {
                            Log.e(TAG, "服务器出现错误！ " );
                            setStop(true);
                            ex.printStackTrace();
//                            Toast.makeText(context, "服务器出现错误！", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onError(Response<String> response) {
                        Log.e(TAG, "网络访问失败！ " );
                        setStop(true);

                    }

                    @Override
                    public void onFinish() {
                        file.delete();
                    }
                });
    }

    //设置是否上传 标识
    public void setStop(boolean flag) {
        stopFlag = flag;
    }

    //获取上传 标识
    public boolean getStopFlag() {
        return stopFlag;
    }

    public BreakpointInfo getInfo() {
        return info;
    }
}
